package com.example.demo.controller;

import com.example.demo.constant.Constants;
import com.example.demo.match.MatchRequest;
import com.example.demo.match.MatchResponse;
import com.example.demo.match.Matcher;
import com.example.demo.match.OnlineUserManager;
import com.example.demo.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
@Slf4j
@Controller
public class MatchController extends TextWebSocketHandler {
    @Autowired
    private Matcher matcher;
    @Autowired
    OnlineUserManager onlineUserManager;

    ObjectMapper mapper=new ObjectMapper();
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //如果当前用户直接访问game_hall.html并没有直接登录,那么WebSocket的session就是空,就会出现空指针异常
        try{
            //1.我们首先要知道当前是谁进入了游戏大厅
            //  用户登录的时候设置了session,注册WebSocket的时候下面的这个方法就是从HTTP中获取session
            //registry.addHandler(matchController,"/findMatch").addInterceptors(new HttpSessionHandshakeInterceptor());
            User user = (User) session.getAttributes().get(Constants.USER_SESSION_KEY);


            //同一个用户,在不同浏览器登录两次,就是"多开",所以用户在进入游戏大厅(哈希表)之前我们要校验下当前大厅是否存在该用户


            if (onlineUserManager.getFromGameHall(user.getUserId())!=null ||
                onlineUserManager.getFromGameRoom(user.getUserId())!=null){
                //不为null,就证明当前用户已经登录
                MatchResponse response=new MatchResponse();
                response.setReason("当前用户已经登录");
                response.setOk(false);
                response.setMessage("repeatConnection");
                session.sendMessage(new TextMessage(mapper.writeValueAsString(response)));
                //因为id相同,关闭连接可能率先登录的用户也会关闭连接,
                //所以我们要通过session会话来确定
                //session.close();
            }



            //2.获取到user对象之后我们将user信息存储到"游戏大厅"中,也就是所谓的"上线"
            //这个哈希表中存储了当前用户的身份信息,我们就认为当前这个用户在线
            //ConcurrentHashMap<Integer, WebSocketSession> gameHall=new ConcurrentHashMap<>();
            onlineUserManager.enterGameHall(user.getUserId(), session);
            log.info("玩家"+ user.getUsername()+"进入游戏大厅");
        }catch(NullPointerException e){
            System.out.println("[afterConnectionEstablished]  NullPointerException");

        }
    }

    @Override
    /**
     * @Param session 当前连接用户的session
     * @Param message 返回数据的格式
     * 处理客户端给服务器发来的请求
     */
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //1.获取当前登录对象
        User user = (User) session.getAttributes().get(Constants.USER_SESSION_KEY);
        System.out.println("玩家1 {}"+user.getUsername()+"进入handleTextMessage");
        //2.处理客户端发来的请求
        String payload=message.getPayload();
        MatchRequest request = mapper.readValue(payload, MatchRequest.class);
        MatchResponse response=new MatchResponse();
        if (request.getMessage().equals("startMatch")){
            matcher.add(user);
            response.setOk(true);
            response.setMessage("startMatch");
        }else if (request.getMessage().equals("stopMatch")){
            matcher.remove(user);
            response.setOk(true);
            response.setMessage("stopMatch");
        }else {
            response.setOk(false);
            response.setReason("IllegalException");
        }
        session.sendMessage(new TextMessage(mapper.writeValueAsString(response)));
    }
    //运行出现异常
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
       //同样,我们这一部分代码也是可以能会出现空指针异常
        try {
            //1.也要从session中拿到当前对象
            User user = (User) session.getAttributes().get(Constants.USER_SESSION_KEY);
            if (user == null) {
                log.warn("会话 {} 的 User 对象为空", session.getId());
                return;
            }

            WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());
            if (tmpSession==session){
                //2.获取到user对象之后我们将user信息在"游戏大厅"中移除,也就是所谓的"下线"
                onlineUserManager.exitGameHall(user.getUserId());
            }
            matcher.remove(user);
            log.info("玩家"+ user.getUsername()+"离开游戏大厅");
        }catch (NullPointerException e){
            System.out.println("[MatchController] handleTransportError 空指针异常");

        }
    }


    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        //同样,我们这一部分代码也是可以能会出现空指针异常
        try {
            //1.也要从session中拿到当前对象
            User user = (User) session.getAttributes().get(Constants.USER_SESSION_KEY);
            if (user == null) {
                log.warn("会话 {} 的 User 对象为空", session.getId());
                return;
            }
            WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());
            if (tmpSession==session){
                //2.获取到user对象之后我们将user信息在"游戏大厅"中移除,也就是所谓的"下线
                onlineUserManager.exitGameHall(user.getUserId());
            }
            matcher.remove(user);
        }catch (NullPointerException e){
            System.out.println("[MatchController] afterConnectionClosed 空指针异常");

        }
    }
}
